package android.slc.icr.core.room.studio;

import android.slc.icr.core.constant.IcrConstants;
import android.slc.icr.core.entity.IcrChartRoom;
import android.slc.icr.core.entity.IcrJoinInfo;
import android.slc.icr.core.entity.IcrMessage;
import android.slc.icr.core.entity.IcrUserInfo;
import android.slc.icr.core.room.manager.IDestroyRoomListener;
import android.slc.icr.core.service.IcrChartRoomMemberService;
import android.slc.icr.core.utils.IcrMessageUtils;
import android.slc.icr.service.IcrMessageRemoteService;
import android.slc.utils.commonlibrary.GsonUtils;
import cn.hutool.core.util.StrUtil;
import io.reactivex.rxjava3.annotations.NonNull;
import org.apache.commons.collections4.Closure;
import org.apache.commons.collections4.IterableUtils;

import java.util.Objects;

/**
 * 聊天室
 */
public abstract class AbsChartRoomStudio {
    //房间信息
    private final IcrChartRoom icrChartRoom;
    //远程消息服务
    private final IcrMessageRemoteService icrMessageRemoteService;
    //远程消息服务
    //房间成员服务
    private final IcrChartRoomMemberService icrChartRoomMemberService;
    //销毁房间监听
    final IDestroyRoomListener destroyRoomListener;

    public AbsChartRoomStudio(IcrChartRoom icrChartRoom,
                              IcrMessageRemoteService icrMessageRemoteService,
                              IcrChartRoomMemberService icrChartRoomMemberService,
                              IDestroyRoomListener destroyRoomListener) {
        this.icrChartRoom = icrChartRoom;
        this.icrMessageRemoteService = icrMessageRemoteService;
        this.icrChartRoomMemberService = icrChartRoomMemberService;
        this.destroyRoomListener = destroyRoomListener;
    }

    /**
     * 获取房间信息
     *
     * @return
     */
    public IcrChartRoom getIcrChartRoom() {
        return icrChartRoom;
    }

    /**
     * 获取消息远程服务
     *
     * @return
     */
    public IcrMessageRemoteService getIcrMessageRemoteService() {
        return icrMessageRemoteService;
    }

    /**
     * 获取房间成员服务
     *
     * @return
     */
    protected final IcrChartRoomMemberService getIcrChartRoomMemberService() {
        return icrChartRoomMemberService;
    }


    /**
     * 操作事件
     *
     * @param icrMessage
     */
    public void onOperateEvent(IcrMessage icrMessage) {
        String action = icrMessage.getAction();
        String sendId = icrMessage.getSender();
        switch (action) {
            //房间消息
            case IcrConstants.Action.ACTION_RTC_SEND_MSG_CHART_ROOM:
                sendMsg2AllMember(IcrConstants.Action.ACTION_RTC_SEND_MSG_CHART_ROOM, icrMessage.getContent());
                break;
            //创建
            case IcrConstants.Action.ACTION_CHART_ROOM_CREATE:
                icrMessageRemoteService.sendMessage(fillMustInfo(getIcrChartRoomId(), sendId,
                        IcrMessage.newBuilder()
                                .setAction(action)
                                .setContent(GsonUtils.toJson(getIcrChartRoom()))
                                .build()));
                break;
            //销毁
            case IcrConstants.Action.ACTION_CHART_ROOM_DESTROY:
                icrMessageRemoteService.sendMessage(fillMustInfo(getIcrChartRoomId(), sendId,
                        IcrMessage.newBuilder()
                                .setAction(IcrConstants.Action.ACTION_CHART_ROOM_DESTROY)
                                .setContent(GsonUtils.toJson(getIcrChartRoom()))
                                .build()));
                sendMsg2AllMember(IcrConstants.Action.ACTION_CHART_ROOM_DESTROY_NOTIFY, getIcrChartRoom());
                break;
            //加入房间
            case IcrConstants.Action.ACTION_CHART_ROOM_JOIN:
                if (getIcrChartRoomMemberService().containsMember(getIcrChartRoomId(), sendId)) {
                    notifyJoinSucceed(sendId);
                    return;
                }
                IcrUserInfo icrUserInfoJoin = ensureJoinRoom(sendId, icrMessage.getContent(), false);
                if (icrUserInfoJoin == null) {
                    //缺少参数
                    IcrMessageUtils.sendActionMissingParam(getIcrMessageRemoteService(), action, createMustInfo(getIcrChartRoomId(), sendId));
                    break;
                }
                //通知加入者加入房间成功
                notifyJoinSucceed(sendId);
                //通知其他成员有用户加入房间
                sendMsg2AllMember(IcrConstants.Action.ACTION_CHART_ROOM_USER_JOIN, icrUserInfoJoin);
                //通知房间成员有变化
                sendMemberChange();
                break;
            //退出房间
            case IcrConstants.Action.ACTION_CHART_ROOM_LEFT:
                IcrUserInfo icrUserInfoLeft = getIcrChartRoomMemberService().findUserInfo(getIcrChartRoomId(), sendId);
                if (icrUserInfoLeft == null) {
                    //不在房间内
                    IcrMessageUtils.sendChartRoomIllicit(getIcrMessageRemoteService(), action, IcrMessageUtils.STR_NOT_IN_ROOM, createMustInfo(getIcrChartRoomId(), sendId));
                    break;
                }
                getIcrMessageRemoteService().sendMessage(fillMustInfo(getIcrChartRoomId(), sendId,
                        IcrMessage.newBuilder()
                                .setAction(IcrConstants.Action.ACTION_CHART_ROOM_LEFT)
                                .setContent(GsonUtils.toJson(icrUserInfoLeft))
                                .build()));
                sendMsg2AllMember(IcrConstants.Action.ACTION_CHART_ROOM_USER_LEFT, icrUserInfoLeft);
                getIcrChartRoomMemberService().removeMember(getIcrChartRoomId(), sendId);
                //通知成员改变
                sendMemberChange();
                break;
        }
    }
    //---------------用户相关 start-------------------------//

    /**
     * 确保用户在房间
     *
     * @param userId
     * @param userInfoJsonStr
     * @param notifyJoinRoom
     */
    protected IcrUserInfo ensureJoinRoom(@NonNull String userId, String userInfoJsonStr, boolean notifyJoinRoom) {
        IcrUserInfo icrUserInfo;
        try {
            icrUserInfo = GsonUtils.fromJson(userInfoJsonStr, IcrUserInfo.class);
        } catch (Exception e) {
            icrUserInfo = IcrUserInfo.newBuilder().setUserId(userId).build();
        }
        return ensureJoinRoom(userId, icrUserInfo, notifyJoinRoom);
    }

    /**
     * 确保用户在房间
     *
     * @param userId
     * @param icrUserInfo
     * @param notifyJoinRoom
     */
    protected IcrUserInfo ensureJoinRoom(@NonNull String userId, @NonNull IcrUserInfo icrUserInfo, boolean notifyJoinRoom) {
        if (StrUtil.isNotEmpty(userId)) {
            IcrUserInfo icrUserInfoJoin = getIcrChartRoomMemberService().findUserInfo(getIcrChartRoomId(), userId);
            if (icrUserInfoJoin == null) {
                icrUserInfo.setUserId(userId);
                icrUserInfoJoin = formatUserInfo(icrUserInfo);
                icrUserInfoJoin.setTimeId(IcrMessageUtils.createTimeId());
                if (icrUserInfoJoin.selfTest()) {
                    icrUserInfoJoin.setCreate(Objects.equals(icrUserInfoJoin.getUserId(), getIcrChartRoom().getCreateUserId()));
                    getIcrChartRoomMemberService().addMember(icrUserInfoJoin);
                    if (notifyJoinRoom) {
                        //此处返回所有用户信息大数据量大的情况下是不合理的
                        notifyJoinSucceed(userId);
                        sendMsg2AllMember(IcrConstants.Action.ACTION_CHART_ROOM_USER_JOIN, icrUserInfoJoin);
                        //通知成员改变
                        sendMemberChange();
                        return icrUserInfoJoin;
                    }
                }
            }
            if (notifyJoinRoom) {
                notifyJoinSucceed(userId);
            }
            return icrUserInfoJoin;
        }
        return null;
    }

    /**
     * 明确用户信息
     *
     * @param userId
     * @param userInfoJsonStr
     * @param addCache
     * @return
     */
    protected IcrUserInfo defineUserInfo(@NonNull String userId, String userInfoJsonStr, boolean addCache) {
        if (StrUtil.isEmpty(userId)) {
            return null;
        }
        IcrUserInfo icrUserInfoJoin = GsonUtils.fromJson(userInfoJsonStr, IcrUserInfo.class);
        if (icrUserInfoJoin == null) {
            icrUserInfoJoin = new IcrUserInfo();
            icrUserInfoJoin.setUserId(userId);
        }
        return defineUserInfo(icrUserInfoJoin, addCache);
    }

    /**
     * 明确用户信息
     *
     * @param icrUserInfo
     * @param addCache    加入到数据库
     * @return
     */
    protected IcrUserInfo defineUserInfo(IcrUserInfo icrUserInfo, boolean addCache) {
        if (icrUserInfo == null || StrUtil.isEmpty(icrUserInfo.getUserId())) {
            return null;
        }
        IcrUserInfo icrUserInfoJoin = getIcrChartRoomMemberService().findUserInfo(getIcrChartRoomId(), icrUserInfo.getUserId());
        if (icrUserInfoJoin != null) {
            return icrUserInfoJoin;
        }
        icrUserInfo = formatUserInfo(icrUserInfo);
        if (icrUserInfo.selfTest()) {
            icrUserInfo.setCreate(Objects.equals(icrUserInfo.getUserId(), getIcrChartRoom().getCreateUserId()));
            if (addCache) {
                getIcrChartRoomMemberService().addMember(icrUserInfo);
                return icrUserInfo;
            }
        }
        return null;
    }

    /**
     * 创建聊天室用户信息
     *
     * @return
     */
    protected final IcrUserInfo formatUserInfo(IcrUserInfo fromIcrUserInfo) {
        if (fromIcrUserInfo == null) {
            return new IcrUserInfo();
        }
        return fromIcrUserInfo.toBuilder()
                .setRelate(getIcrChartRoom().getRoomType())
                .setRelateId(getIcrChartRoom().getRoomId())
                .setUserId(fromIcrUserInfo.getUserId())
                .build();
    }

    //---------------用户相关 end-------------------------//

    //---------------消息发送 start-------------------------//

    /**
     * 通知加入房间成功
     *
     * @param sendId
     */
    private void notifyJoinSucceed(String sendId) {
        //此处会返回直播间所有的用户信息，显然这样是不合理的，正确做法是让加入者自己通过http请求在实现相关业务获取
        getIcrMessageRemoteService().sendMessage(fillMustInfo(getIcrChartRoomId(), sendId,
                IcrMessage.newBuilder()
                        .setAction(IcrConstants.Action.ACTION_CHART_ROOM_JOIN)
                        .setContent(GsonUtils.toJson(new IcrJoinInfo(getIcrChartRoom(),
                                getIcrChartRoomMemberService().findUserInfo(getIcrChartRoomId(), sendId),
                                getIcrChartRoomMemberService().getAllMember(getIcrChartRoomId()))))
                        .build()));
    }

    /**
     * 发送给所有用户
     *
     * @param action
     * @param content
     */
    protected void sendMsg2AllMember(String action, Object content) {
        IterableUtils.forEach(icrChartRoomMemberService.getAllMember(getIcrChartRoomId()), new Closure<IcrUserInfo>() {
            @Override
            public void execute(IcrUserInfo icrUserInfo) {
                IcrMessage.Builder builder = IcrMessage.newBuilder().setAction(action);
                if (content != null) {
                    if (content instanceof String) {
                        builder.setContent((String) content);
                    } else {
                        builder.setContent(GsonUtils.toJson(content));
                    }
                }
                IcrMessage icrMessage = builder.build();
                fillMustInfo(getIcrChartRoomId(), icrUserInfo.getUserId(), icrMessage);
                icrMessageRemoteService.sendMessage(icrMessage);
            }
        });
    }

    /**
     * 发送成员变化消息
     */
    protected void sendMemberChange() {
        IterableUtils.forEach(icrChartRoomMemberService.getAllMember(getIcrChartRoomId()),
                userInfo -> icrMessageRemoteService.sendMessage(fillMustInfo(getIcrChartRoomId(), userInfo.getUserId(), IcrMessage.newBuilder()
                        .setAction(IcrConstants.Action.ACTION_CHART_ROOM_MEMBER_CHANGE)
                        .setContent(String.valueOf(icrChartRoomMemberService.getMemberSize(getIcrChartRoomId()))).build())));
    }

    /**
     * 发送销毁房间消息
     */
    protected void sendDestroyRoom() {
        destroyRoomListener.onDestroyRoom(getIcrChartRoom().getCreateUserId(), getIcrChartRoomId());
    }

    /**
     * 填充必要的信息
     *
     * @param sendId
     * @param receiveId
     * @param icrMessage
     * @return
     */
    protected IcrMessage fillMustInfo(String sendId, String receiveId, IcrMessage icrMessage) {
        icrMessage.setSender(sendId);
        icrMessage.setReceiver(receiveId);
        icrMessage.setRelate(getIcrChartRoom().getRoomType());
        icrMessage.setRelateId(getIcrChartRoom().getRoomId());
        return icrMessage;
    }

    /**
     * 创建必要信息
     *
     * @param sendId
     * @param receiveId
     * @return
     */
    protected IcrMessage createMustInfo(String sendId, String receiveId) {
        return fillMustInfo(sendId, receiveId, IcrMessage.newBuilder().build());
    }

    //---------------消息发送 end-------------------------//

    public String getIcrChartRoomId() {
        return getIcrChartRoom().getRoomId();
    }

    /**
     * 销毁
     */
    public void destroy() {
    }
}
